import Core.Basic
from Core.package import *
import pathlib
import requests
from PIL import Image
import io
import os


class Worker_Thread(QThread):
    thread_task_data = Signal(dict)
    Current_Download_Process = Signal(int)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.task_data = dict()

    def convert_image_to_jpg(self, image_data, save_path):
        """将图片数据转换为JPG格式并保存"""
        try:
            # 使用PIL打开图片
            with Image.open(io.BytesIO(image_data)) as img:
                # 如果是RGBA模式（有透明通道），转换为RGB
                if img.mode in ('RGBA', 'LA'):
                    background = Image.new(
                        img.mode[:-1], img.size, (255, 255, 255))
                    background.paste(img, img.split()[-1])
                    img = background
                elif img.mode == 'P':  # 处理调色板模式
                    img = img.convert('RGB')

                # 保存为JPG格式，质量设为95
                img.save(save_path, 'JPEG', quality=95)
            return True
        except Exception as e:
            print(f"图片转换失败: {e}")
            # 转换失败时，直接保存原始数据
            with open(save_path, 'wb') as f:
                f.write(image_data)
            return False

    def run(self):
        try:
            # 获取请求头
            driver = Core.Basic.GlobalVar.driver
            user_agent = driver.execute_script("return navigator.userAgent;")
            download_directory = pathlib.Path(
                "./Data/Product_Download_File").absolute().resolve()
            download_save_directory_name = pathlib.Path(
                self.task_data['download_json_file_path']).absolute().resolve().stem
            download_mainimage_directory = pathlib.Path(download_directory).joinpath(
                download_save_directory_name).joinpath("主图")
            download_detailimage_directory = pathlib.Path(download_directory).joinpath(
                download_save_directory_name).joinpath("详情图")
            download_skuimage_directory = pathlib.Path(download_directory).joinpath(
                download_save_directory_name).joinpath("SKU")
            download_video_directory = pathlib.Path(download_directory).joinpath(
                download_save_directory_name).joinpath("视频")
            CurrentDownloadCount = int(0)

            # 计算所有下载图片的数量
            CurrentDownloadCount = int(0)
            DownloadCount = len(self.task_data['main_images_list']) \
                + len(self.task_data['detail_images_url']) \
                + len(self.task_data['sku_list'])

            if self.task_data['main_video_url']:
                DownloadCount += 1

            # 1.下载主图图片
            for index, image_url in enumerate(self.task_data['main_images_list'], start=1):
                print(f"提示 : 正在下载第 {index} 张主图图片...")
                response = requests.get(url=image_url, headers={
                                        "User-Agent": user_agent})
                savefilename = f"Main-{index:03d}.jpg"
                download_mainimage_directory.mkdir(parents=True, exist_ok=True)
                savepath = download_mainimage_directory.joinpath(savefilename)

                # 转换并保存为JPG
                self.convert_image_to_jpg(response.content, savepath)

                CurrentDownloadCount += 1
                self.Current_Download_Process.emit(
                    int(CurrentDownloadCount/DownloadCount*100))

            # 2.下载详情图片
            for index, image_url in enumerate(self.task_data['detail_images_url'], start=1):
                print(f"提示 : 正在下载第 {index} 张详情图片...")
                response = requests.get(url=image_url, headers={
                                        "User-Agent": user_agent})
                savefilename = f"Detail-{index:03d}.jpg"
                download_detailimage_directory.mkdir(
                    parents=True, exist_ok=True)
                savepath = download_detailimage_directory.joinpath(
                    savefilename)

                # 转换并保存为JPG
                self.convert_image_to_jpg(response.content, savepath)

                CurrentDownloadCount += 1
                self.Current_Download_Process.emit(
                    int(CurrentDownloadCount/DownloadCount*100))

            # 3.下载SKU图片
            for index, sku_data in enumerate(self.task_data['sku_list'], start=1):
                print(f"提示 : 正在下载第 {index} 张sku图片...")
                response = requests.get(url=sku_data['sku_img_url'], headers={
                                        "User-Agent": user_agent})
                savefilename = f"Sku_{index:03d}_{sku_data['sku_label']}.jpg"

                download_skuimage_directory.mkdir(parents=True, exist_ok=True)
                savepath = download_skuimage_directory.joinpath(savefilename)

                # 转换并保存为JPG
                self.convert_image_to_jpg(response.content, savepath)

                CurrentDownloadCount += 1
                self.Current_Download_Process.emit(
                    int(CurrentDownloadCount/DownloadCount*100))

            # 4.下载视频
            if self.task_data['main_video_url']:
                with requests.get(url=self.task_data['main_video_url'], headers={"User-Agent": user_agent}, stream=True, timeout=5) as response:
                    # 检查请求是否成功
                    response.raise_for_status()

                    # 打开文件准备写入
                    download_video_directory.mkdir(parents=True, exist_ok=True)
                    savepath = download_video_directory.joinpath(
                        "Main_Video.mp4")

                    with open(savepath, 'wb') as file:
                        # 分块写入，每次读取 1024*1024 字节（1MB）
                        for chunk in response.iter_content(chunk_size=1024*1024):
                            if chunk:  # 确保 chunk 不是空的
                                file.write(chunk)
                                file.flush()  # 刷新缓冲区，立即写入磁盘

                CurrentDownloadCount += 1
                self.Current_Download_Process.emit(
                    int(CurrentDownloadCount/DownloadCount*100))

        except Exception as e:
            print(f"提示 : 员工线程任务发生错误!\n错误信息: {e}")
        finally:
            self.thread_task_data.emit(self.task_data)

    def __delattr__(self, name):
        print(f"提示 : 子任务子线程运行结束!正在销毁资源 {self}")
        return super().__delattr__(name)


class Staff_DownloadFile(QObject):
    Start_Task = Signal()   # 任务开始信号,启动任务时,请发送此信号
    Task_Finish = Signal()   # 任务完成信号,任务结束时候,请发送此信号
    Current_Completion_Process = Signal(int)
    Emergency_Stop = Signal()  # 紧急停止信号
    OnlyRun = Signal()  # 仅运行信号

    def __init__(self, parent=None):
        super().__init__(parent)
        self.Start_Task.connect(self.RunTask)

    @Slot(str)
    def slot_fun(self, text):
        print(f"我是槽函数,我是 {text}")

    # 设置员工属性
    def Set_Staff_Attribute(self, ** kwargs):
        """设置员工对象的属性，用于后续任务执行
        """
        for key, value in kwargs.items():
            setattr(self, key, value)
        print(f"已设置属性: {kwargs.keys()}")

    def RunTask(self):
        # 获取需要操作的 主线程 窗口的 UI 对象
        # 使用 self.parent() 获取父对象
        self.parent_widget = self.parent()
        if self.parent_widget is None:
            print(f"提示 : 父对象为空!\n请将创建员工对象时,将父对象作为参数传入!")
            return
        # 获取 任务按钮 UI 控件对象
        self.task_button_object_name = "pushButton_download_product_data_file"
        self.task_button: QPushButton = self.parent().findChild(
            QPushButton, self.task_button_object_name)
        if self.task_button is None:
            print(f"提示 : 程序无法找到 {self.task_button_object_name} 对应的按钮!")
            print(f"提示 : 子任务结束!")
            return
        self.task_progressbar_object_name = "progressBar_download"
        self.task_progressbar: QProgressBar = self.parent().findChild(
            QProgressBar, self.task_progressbar_object_name)
        if self.task_progressbar is None:
            print(f"提示 : 程序无法找到 {self.task_progressbar_object_name} 对应的进度条!")
            print(f"提示 : 子任务结束!")
            return
        self.list_widget_object_name = "listWidget_configfile_list"
        self.list_widget: QListWidget = self.parent().findChild(
            QListWidget, self.list_widget_object_name)
        if self.list_widget is None:
            print(
                f"提示 : 获取 {self.list_widget_object_name} 对应的 listwidget 列表失败!")
            print(f"提示 : 子任务结束!")
            return
        self.textedit_object_name = "textEdit_current_download_config_data"
        self.textedit: QTextEdit = self.parent().findChild(
            QTextEdit, self.textedit_object_name)
        if self.textedit is None:
            print(f"提示 : 获取 {self.textedit_object_name} 对应的 textedit 文本编辑框失败!")
            print(f"提示 : 子任务结束!")
            return

        # 创建子线程
        self.workerthread = Worker_Thread()
        if not self.textedit.toPlainText():
            print(f"提示 : 当前没有数据!")
            return
        json_file_path = pathlib.Path("./Data/Product_Collection_ConfigFile").joinpath(
            self.list_widget.currentItem().text()).absolute().resolve()
        try:
            self.workerthread.task_data = json.loads(
                s=self.textedit.toPlainText())
            self.workerthread.task_data['download_json_file_path'] = json_file_path.__str__(
            )
        except:
            QMessageBox.information(
                self.parent_widget, f"错误", f"提示 : 配置文件 \n{json_file_path} 无法成功解析为 dict 数据类型!")
            return

        # 绑定信号
        self.workerthread.finished.connect(
            lambda: QMessageBox.information(self.parent_widget, "提示", "下载任务完成!"))
        self.workerthread.finished.connect(
            lambda: self.Task_Finish.emit())    # 子线程运行结束代表该员工类的任务结束
        self.workerthread.finished.connect(
            lambda: self.workerthread.quit())   # 线程结束，销毁线程
        self.workerthread.finished.connect(lambda: self.deleteLater())
        self.workerthread.finished.connect(
            lambda: self.task_button.setEnabled(True))

        self.workerthread.Current_Download_Process.connect(
            lambda count: self.task_progressbar.setValue(count))

        # 启动子线程,开始执行任务
        self.task_button.setEnabled(False)
        self.workerthread.start()


if __name__ == "__main__":
    import sys
    from PySide6.QtWidgets import QApplication
    app = QApplication(sys.argv)
    # 编写 控制台 程序
    staff = Staff_DownloadFile(app)
    staff.RunTask()

    sys.exit(app.exec_())
